//
//  BBRadialControlView.m
//  xNose
//
//  Created by ben smith on 9/10/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "BBRadialControlView.h"
#import "BBDefaultController.h"
#import "BBNodeView.h"
#import "BBNode.h"


@implementation BBRadialControlView

@synthesize delegate;

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here
			costStartOffset = 60;
			incomeStartOffset = 45;
    }
    return self;
}

-(void)setDelegate:(BBNodeView*)d
{
	[self.delegate removeObserver:self forKeyPath:@"node.income"];
	[self.delegate removeObserver:self forKeyPath:@"node.cost"];

	[d retain];
	[delegate release];
	delegate = d;

	[self setPoints];
	
	[self.delegate addObserver:self forKeyPath:@"node.income" options:NSKeyValueObservingOptionNew context:nil];
	[self.delegate addObserver:self forKeyPath:@"node.cost" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
	[self setNeedsDisplay:YES];
}

-(void)setPoints
{
	[self setRadius];
	// find the points for the various controls
	// calculate the positions of the control points
	NSPoint center = NSMakePoint(NSMidX([self bounds]), NSMidY([self bounds]));	

	float maxVal = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBMaxRadialValue"];
	float valuePerDegree = maxVal/360;
	
	costStart = [self pointForAngle:costStartOffset radius:costRadius around:center];
	costEnd = [self pointForAngle:costStartOffset + (delegate.node.cost/valuePerDegree) radius:costRadius around:center];
	
	incomeStart = [self pointForAngle:incomeStartOffset radius:incomeRadius around:center];
	incomeEnd = [self pointForAngle:incomeStartOffset + (delegate.node.income/valuePerDegree) radius:incomeRadius around:center];
	
}


-(void)setRadius
{
	float controlSize = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBRadialControlSize"];
	
	float smallerDim = NSHeight(self.bounds);
	if (NSWidth(self.bounds) < NSHeight(self.bounds)) smallerDim = NSWidth(self.bounds);
	
	float width = smallerDim - controlSize - 3; 
	
	incomeRadius = width/2.0;
	
	costRadius = incomeRadius - controlSize;	
	profitRadius = costRadius - controlSize;	
}

- (void)drawRect:(NSRect)rect {
    // Drawing code here.
	if (delegate == nil) return;
	[self setPoints];
	
	[[NSColor whiteColor] set];
	[NSBezierPath setDefaultLineWidth:2.0];

	NSPoint center = NSMakePoint(NSMidX(self.bounds), NSMidY(self.bounds));
	float startAngle = [self angleOfPoint:incomeStart around:center] - 90.0;
	float endAngle = [self angleOfPoint:incomeEnd around:center] - 90.0;
	[self drawRingWithStart:startAngle end:endAngle radius:incomeRadius color:[BBDefaultController incomeColor]];

	[[BBDefaultController incomeColor] set];
	[self drawControlAtPoint:incomeStart];
	[[BBDefaultController incomeColor] set];
	[self drawControlAtPoint:incomeEnd];

	
	startAngle = [self angleOfPoint:costStart around:center] - 90.0;
	endAngle = [self angleOfPoint:costEnd around:center] - 90.0;
	[self drawRingWithStart:startAngle end:endAngle radius:costRadius color:[BBDefaultController costColor]];
	[[BBDefaultController costColor] set];
	[self drawControlAtPoint:costStart];
	[[BBDefaultController costColor] set];
	[self drawControlAtPoint:costEnd];

	NSRect outer = NSMakeRect(center.x - profitRadius, center.y - profitRadius, profitRadius * 2.0, profitRadius * 2.0);
	NSBezierPath * outerPath = [NSBezierPath bezierPathWithOvalInRect:outer];
	
	[[BBDefaultController profitColor] set];
	[outerPath fill];
	[[NSColor whiteColor] set];
	[outerPath stroke];	
	
	// now draw the text in
	
	NSMutableParagraphStyle * style = [[NSMutableParagraphStyle alloc] init];
	[style setParagraphStyle:[NSParagraphStyle defaultParagraphStyle]];
	[style setAlignment:NSCenterTextAlignment];
	
	NSFont * thisFont = [BBDefaultController regularLargeFont];
	float height = [BBDefaultController fontHeight:thisFont];
	
	NSDictionary * theseAttributes = [NSDictionary dictionaryWithObjectsAndKeys:thisFont,NSFontAttributeName,[NSColor whiteColor],NSForegroundColorAttributeName,style,NSParagraphStyleAttributeName,nil];
	[style release];
	
	NSString * profit = [NSString stringWithFormat:@"%@",[[BBDefaultController percentFormatter] stringFromNumber:[NSNumber numberWithFloat:delegate.node.profit]]];
	
	
	NSRect textRect = outer;
	textRect.size.height = height;
	textRect.origin.y += (NSHeight(outer) - height)/2.0;
	
	[profit drawInRect:textRect withAttributes:theseAttributes];
	
//	[[NSColor redColor] set];
//	[NSBezierPath strokeRect:self.bounds];
}

-(void)drawRingWithStart:(float)startAngle end:(float)endAngle radius:(float)radius color:(NSColor*)color
{
	NSPoint center = NSMakePoint(NSMidX(self.bounds), NSMidY(self.bounds));
	NSRect outer = NSMakeRect(center.x - radius, center.y - radius, radius * 2.0, radius * 2.0);
	NSBezierPath * outerPath = [NSBezierPath bezierPathWithOvalInRect:outer];

	[[NSColor colorWithDeviceWhite:0.0 alpha:0.45] set];
	[outerPath fill];
	
	NSBezierPath * outerRadial = [NSBezierPath bezierPath];
	[outerRadial moveToPoint:center];
	[outerRadial appendBezierPathWithArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle];
	[outerRadial lineToPoint:center];
	
	[[color colorWithAlphaComponent:0.85] set];
	[outerRadial fill];	
	
	[[NSColor whiteColor] set];
	[outerPath stroke]; //37 121 110
	
}

-(NSRect)controlRectAtPoint:(NSPoint)p
{
	float controlSize = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBRadialControlSize"];
	float radius = controlSize/2.0;
	return NSMakeRect(p.x - radius, p.y - radius, radius * 2.0, radius * 2.0);	
}

-(void)drawControlAtPoint:(NSPoint)p
{
	NSPoint center = NSMakePoint(NSMidX(self.bounds), NSMidY(self.bounds));
	[NSBezierPath strokeLineFromPoint:center toPoint:p];
	NSBezierPath * c1Path = [NSBezierPath bezierPathWithOvalInRect:[self controlRectAtPoint:p]]; 
	[c1Path fill];
	[[NSColor whiteColor] set];
	[c1Path stroke];	
}


-(void)otherMouseDown:(NSEvent*)theEvent
{
	[self mouseDown:theEvent];	
}

-(void)otherMouseDragged:(NSEvent*)theEvent
{
	[self mouseDragged:theEvent];	
}


-(void)mouseDown:(NSEvent*)theEvent
{
	mouseDown = [[[self window] contentView] convertPoint:[theEvent locationInWindow] toView:self];
	costStartAdjust = costEndAdjust = NO;
	incomeStartAdjust = incomeEndAdjust = NO;
	
	if (NSPointInRect(mouseDown, [self controlRectAtPoint:costStart])) {
		costStartAdjust = YES;
		return;
	}
	if (NSPointInRect(mouseDown, [self controlRectAtPoint:costEnd])) {
		costEndAdjust = YES;
		return;
	}

	if (NSPointInRect(mouseDown, [self controlRectAtPoint:incomeStart])) {
		incomeStartAdjust = YES;
		return;
	}
	if (NSPointInRect(mouseDown, [self controlRectAtPoint:incomeEnd])) {
		incomeEndAdjust = YES;
		return;
	}
	
}

-(void)mouseDragged:(NSEvent*)theEvent
{
	// ok if one of our doohickies is adjusting then we need to do a few things:
	// first see how big of an angle we have adjusted
	// then figure out if we have a smaller slice or a bigger slice
	// figure out how much the slice is now
	// set the node value
	// if we are adjusting the start of one of our controls, then adjust it by the amount
	NSPoint thisMouseDown = [[[self window] contentView] convertPoint:[theEvent locationInWindow] toView:self];
	
	NSPoint center = NSMakePoint(NSMidX([self bounds]), NSMidY([self bounds]));	

	float thisAngle = [self angleOfPoint:thisMouseDown around:center];
	float downAngle = [self angleOfPoint:mouseDown around:center];
	
	mouseDown = thisMouseDown;
	
	
	float adjustDegrees = thisAngle - downAngle;
	// two tries, once for each direction
	if (fabs(adjustDegrees) > 180.0) {
		// then maybe try to do it the other way
		float newAdjustDegrees =  (thisAngle - 360.0) - downAngle;
		if (fabs(newAdjustDegrees) > 180.0) {
			// then maybe try to do it the other way
			adjustDegrees =  (thisAngle + 360) - downAngle;
		} else {
			adjustDegrees = newAdjustDegrees;
		}
	}

	// find out how much that is in dollars
	float maxVal = [[NSUserDefaults standardUserDefaults] floatForKey:@"BBMaxRadialValue"];

	float valuePerDegree = maxVal/360.0;
	float adjustValue = valuePerDegree * adjustDegrees; //easy!
	
	// if this is not enough to care about (ie less than 1) then abandon hope
	
	// nope, we have a winner, chop it down to an int value
//	adjustValue = floor(adjustValue);
	// now figure out what we are adjusting
	
	if (costStartAdjust) {
		// then we need to adjust the amount of cost as well as teh start offset
		costStartOffset += adjustDegrees;
		delegate.node.cost -= adjustValue;
	}
	if (costEndAdjust) {
		// then we need to adjust the amount of cost as well as teh start offset
		delegate.node.cost += adjustValue;
	}
	if (incomeStartAdjust) {
		// then we need to adjust the amount of cost as well as teh start offset
		incomeStartOffset += adjustDegrees;
		delegate.node.income -= adjustValue;
	}
	if (incomeEndAdjust) {
		// then we need to adjust the amount of cost as well as teh start offset
		delegate.node.income += adjustValue;
	}
	
	
	[self setNeedsDisplay:YES];
}

-(void)mouseUp:(NSEvent*)theEvent
{
	
}

-(float)angleOfPoint:(NSPoint)p around:(NSPoint)center
{
	float opposite = p.y - center.y;
	float adjacent = p.x - center.x;
	float radians = atanf(opposite/adjacent);
	float degrees = (radians * 57.2957795) + 90.0;
	if (adjacent < 0) degrees += 180;
	return degrees;
}


-(NSPoint)pointForAngle:(float)angle radius:(float)radius around:(NSPoint)center
{
	// calculate the control rect
	angle -= 90;
	angle /= 57.2957795; //convert to radians
	NSPoint mid;
	mid.x = center.x + (radius * cosf(angle)); 
	mid.y = center.y + (radius * sinf(angle));
	return mid;
}

- (void) dealloc
{
	[self setDelegate:nil];
	[super dealloc];
}


@end
